LaptopQuartet1{
	var instrument, adr, prt, <>win, buttons, <>slider, letters, notes, <>synths, fund, addr, player;
	var localAddr, s;
	
	*new { arg instrument, adr, prt;
		^super.newCopyArgs(instrument,adr,prt).init;
	}
	
	init {
		if (instrument.isNil, {instrument = "QuartetBass"});
		if (adr.isNil, {adr = "127.0.0.1"});
		if (prt.isNil, {prt = 57120});
		if(instrument == "QuartetBass",{player = 0;});
		if(instrument == "QuartetTenor",{player = 1;});
		if(instrument == "QuartetAlto",{player = 2;});
		if(instrument == "QuartetSoprano",{player = 3;});
		
		s = Server.local;
		
		letters = [
			["1","2","3","4","5","6","7","8","9","0"],
			["q","w","e","r","t","y","u","i","o","p"],
			["a","s","d","f","g","h","j","k","l",";"],
			["z","x","c","v","b","n","m",",",".","/"]
		];

		fund = 55;
		notes = [0,0,0,0];
		notes[0] = [
			Array.series(10, fund*(38/29), (fund/2)*(38/29)),
			Array.series(10, fund*(11/9), (fund/2)*(11/9)),
			Array.series(10, fund*(9/8), (fund/2)*(9/8)),
			Array.series(10, fund, (fund/2))
		];
		
		fund = 110;
		notes[1] = [
			Array.series(10, fund*(38/29), (fund/2)*(38/29)),
			Array.series(10, fund*(11/9), (fund/2)*(11/9)),
			Array.series(10, fund*(9/8), (fund/2)*(9/8)),
			Array.series(10, fund, (fund/2))
		];
		
		fund = 220;
		notes[2] = [
			Array.series(10, fund*(38/29), (fund/2)*(38/29)),
			Array.series(10, fund*(11/9), (fund/2)*(11/9)),
			Array.series(10, fund*(9/8), (fund/2)*(9/8)),
			Array.series(10, fund, (fund/2))
		];
		
		fund = 220;
		notes[3] = [
			Array.series(10, fund*(38/29), (fund/2)*(38/29)),
			Array.series(10, fund*(11/9), (fund/2)*(11/9)),
			Array.series(10, fund*(9/8), (fund/2)*(9/8)),
			Array.series(10, fund, (fund/2))
		];
		
		addr = NetAddr(adr,prt);
		
		if(addr.port != 57120,{localAddr = NetAddr("127.0.0.1",57120)});
		
		synths = [[],[],[],[]];
		
		4.do{ arg i;
		synths[i] = [
			Array.fill(10,0),
			Array.fill(10,0),
			Array.fill(10,0),
			Array.fill(10,0)
		];
		};
		
		~noteResponder.remove;
		~sliderResponder.remove;
		
		(
		~noteResponder = OSCresponderNode(nil,'/quartetNote',{ arg time, resp, msg;
			var group;
			//[msg[1],msg[2],msg[3],msg[4],msg[5],msg[6]].postln;
			
			if(msg[1].asString == "QuartetBass",{group = 0;});
			if(msg[1].asString == "QuartetTenor",{group = 1;});
			if(msg[1].asString == "QuartetAlto",{group = 2;});
			if(msg[1].asString == "QuartetSoprano",{group = 3;});
			
			if(msg[4] == 1,{
				synths[group][msg[3]][msg[2]] = Synth(msg[1],[
					"freq",notes[group][msg[3]][msg[2]],
					"amp",msg[6],
					"timbre",msg[5]
				]);

			},{
				synths[group][msg[3]][msg[2]].release();
			});
			
		}).add;
		);
		
		(
		~sliderResponder = OSCresponderNode(nil,'/quartetSlider',{ arg time, resp, msg;
			var group;
			//[msg[1],msg[2],msg[3],msg[4],msg[5],msg[6]].postln;
			
			if(msg[1].asString == "QuartetBass",{group = 0;});
			if(msg[1].asString == "QuartetTenor",{group = 1;});
			if(msg[1].asString == "QuartetAlto",{group = 2;});
			if(msg[1].asString == "QuartetSoprano",{group = 3;});
			
			synths[group][msg[3]][msg[2]].set("amp",msg[5]);
			synths[group][msg[3]][msg[2]].set("timbre",msg[4]);
			
		}).add;
		);
		
		this.initSynthDefs;
		this.makeWin;
		
	}
	
	initSynthDefs {
	
		(
		SynthDef("QuartetBass",{ arg freq = 55, amp = 0.3, out = 0, pan = 0.3, gate = 1, timbre = 1;
			var sig, lowsig, bow, env;
			
			env = EnvGen.kr(Env.adsr(0.05, 0.25, 0.6, 0.4, 1, 'sine'), gate, doneAction:2);
			
			bow = PinkNoise.ar(0.012);
			
			sig = Klank.ar(`[
				Array.series(15, 1),
				Array.geom(15, 1, 0.8),
				Array.geom(15, 1.6, 0.9)
			],
			bow,
			freq);
			
			sig = RHPF.ar(sig, LFNoise2.kr(1,freq*0.1,freq*timbre), 0.07, 0.4);
			
			sig = RLPF.ar(sig, LFNoise2.kr(1,freq*0.3,freq*15), 0.5, 0.4);
			
			Out.ar(out,Pan2.ar(sig,pan,env*amp));
		}).store;
		);
		
		(
		SynthDef("QuartetTenor",{ arg freq = 55, amp = 0.3, out = 0, pan = -0.3, gate = 1, timbre = 1;
			var sig, bow, env;
			
			env = EnvGen.kr(Env.adsr(0.05, 0.25, 0.6, 0.4, 1, 'sine'), gate, doneAction:2);
			
			bow = PinkNoise.ar(0.012);
			
			sig = Klank.ar(`[
				Array.series(15, 1),
				Array.geom(15, 1, 0.8),
				Array.geom(15, 1.6, 0.9)
			],
			bow,
			freq);
			
			sig = RHPF.ar(sig, LFNoise2.kr(1,freq*0.1,freq*timbre), 0.07, 0.4);
			
			sig = RLPF.ar(sig, LFNoise2.kr(1,freq*0.3,freq*15), 0.5, 0.4);
			
			Out.ar(out,Pan2.ar(sig,pan,env*amp));
		}).store;
		);
		
		(
		SynthDef("QuartetAlto",{ arg freq = 55, amp = 0.3, out = 0, pan = 0.6, gate = 1, timbre = 1;
			var sig, bow, env;
			
			env = EnvGen.kr(Env.adsr(0.05, 0.25, 0.6, 0.4, 1, 'sine'), gate, doneAction:2);
			
			bow = PinkNoise.ar(0.012);
			
			sig = Klank.ar(`[
				Array.series(13, 1),
				Array.geom(13, 1, 0.8),
				Array.geom(13, 1.6, 0.9)
			],
			bow,
			freq);
			
			sig = RHPF.ar(sig, LFNoise2.kr(1,freq*0.1,freq*timbre), 0.07, 0.4);
			
			sig = RLPF.ar(sig, LFNoise2.kr(1,freq*0.3,freq*15), 0.5, 0.4);
			
			Out.ar(out,Pan2.ar(sig,pan,env*amp));
		}).store;
		);
		
		(
		SynthDef("QuartetSoprano",{ arg freq = 55, amp = 0.3, out = 0, pan = -0.6, gate = 1, timbre = 1;
			var sig, bow, env;
			
			env = EnvGen.kr(Env.adsr(0.05, 0.25, 0.6, 0.4, 1, 'sine'), gate, doneAction:2);
			
			bow = PinkNoise.ar(0.012);
			
			sig = Klank.ar(`[
				Array.series(11, 1),
				Array.geom(11, 1, 0.8),
				Array.geom(11, 1.6, 0.9)
			],
			bow,
			freq);
			
			sig = RHPF.ar(sig, LFNoise2.kr(1,freq*0.1,freq*timbre), 0.07, 0.4);
			
			sig = RLPF.ar(sig, LFNoise2.kr(1,freq*0.3,freq*15), 0.5, 0.4);
			
			Out.ar(out,Pan2.ar(sig,pan,env*amp));
		}).store;
		);

	}
	
	makeWin {
		win = Window.new(instrument, Rect(100,100,680,200), false).front;
		
		slider = Slider2D(win,Rect(490,10,180,180))
		.x_(0.3)
		.y_(0.3)
		.keyDownAction_({ arg char, modifiers, unicode,keycode;
			// standard keydown
			if (char == $r, {});
			if (char == $n, {});
			if (char == $x, {});
			if (char == $c, {});
			if (unicode == 16rF700, {});
			if (unicode == 16rF703, {});
			if (unicode == 16rF701, {});
			if (unicode == 16rF702, {});
		});
		
		buttons = [[],[],[],[]];
		
		letters.size.do({ arg y;
			letters[y].size.do({ arg x;
				buttons[y] = buttons[y].add(
					Button(win,Rect(((x*46)+10)+(y*4),(y*46)+10,44,44))
					.states_([
						[letters[y][x],Color.black,Color.white],
						[letters[y][x],Color.white,Color.black]
					])
					.action_({ arg state;
						if(state.value == 1,
							{
							/*
							synths[player][y][x] = Synth(instrument.asString,[
								"freq",notes[y][x],
								"amp",(slider.y*0.7)+0.005,
								"timbre",(slider.x*6)+0.5
							]);
							*/
							addr.sendMsg(
								"/quartetNote",
								instrument,
								x,
								y,
								1,
								(slider.x*9)+0.5,
								(slider.y*1.7)+0.005
							);
							
							if(localAddr.notNil,{
								localAddr.sendMsg(
								"/quartetNote",
								instrument,
								x,
								y,
								1,
								(slider.x*9)+0.5,
								(slider.y*1.7)+0.005
							)
							});
							
							},
							{
							//synths[player][y][x].release();
							addr.sendMsg("/quartetNote",instrument,x,y,0);
							if(localAddr.notNil,{
								localAddr.sendMsg("/quartetNote",instrument,x,y,0);
							});
							}
						);
					});
				);
			});
		});
		
		win.view.keyDownAction = { arg view, char, modifiers, unicode, keycode;  
			letters.size.do({ arg y;
				letters[y].size.do({ arg x;
					if(char.asString == letters[y][x],{
						if(buttons[y][x].value != 1,{
							buttons[y][x].valueAction_(1);
							/*
							addr.sendMsg(
								"/quartetNote",
								instrument,
								x,
								y,
								1,
								(slider.x*6)+0.5,
								(slider.y*0.7)+0.005
							);
							*/
						});
					});
				});
			});
		};
		win.view.keyUpAction = { arg view, char, modifiers, unicode, keycode;  
			buttons.size.do({ arg y;
				buttons[y].size.do({ arg x;
					if(char.asString == letters[y][x],{
						buttons[y][x].valueAction_(0);
						//addr.sendMsg("/quartetNote",instrument,x,y,0);
					});
				});
			});
		};
		
		slider.action_({
		buttons.size.do{ arg y;
			buttons[y].size.do{ arg x;
				if(buttons[y][x].value == 1,{
				/*
				synths[player][y][x].set("amp",(slider.y*0.7)+0.005);
				synths[player][y][x].set("timbre",(slider.x*6)+0.5);
				*/
				addr.sendMsg("/quartetSlider",instrument,x,y,(slider.x*9)+0.5,(slider.y*1.7)+0.005);
				if(localAddr.notNil,{
					localAddr.sendMsg("/quartetSlider",instrument,x,y,(slider.x*6)+0.5,(slider.y*1.7)+0.005);
				});
				})
			};
		};
		});
		
		win.onClose_({
		~noteResponder.remove;
		~sliderResponder.remove;
		});
	}
}